package org.abc.fund.config.exception;

import lombok.extern.slf4j.Slf4j;
import org.abc.fund.util.exception.ResourceNotFoundException;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.HttpStatusCode;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.context.request.WebRequest;
import org.springframework.web.server.ResponseStatusException;
import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler;

import java.time.OffsetDateTime;
import java.util.HashMap;
import java.util.Map;

/** 全局REST异常处理器类，用于处理控制器中抛出的异常 */
@ControllerAdvice
@Slf4j
public class RestExceptionHandler extends ResponseEntityExceptionHandler {

  /**
   * 处理资源未找到异常的方法 当抛出ResourceNotFoundException时调用此方法
   *
   * @param ex 资源未找到异常
   * @param request Web请求对象
   * @return 返回包含错误信息的HTTP响应实体
   */
  @ExceptionHandler(value = {ResourceNotFoundException.class})
  protected ResponseEntity<Object> handleResourceNotFound(
      ResourceNotFoundException ex, WebRequest request) {
    return handleExceptionInternal(
        ex, ex.getMessage(), new HttpHeaders(), HttpStatus.NOT_FOUND, request);
  }

  /**
   * 处理非法参数异常的方法
   *
   * @param ex 非法参数异常
   * @param request Web请求对象
   * @return 返回包含错误信息的HTTP响应实体
   */
  @ExceptionHandler(value = {IllegalArgumentException.class, IllegalStateException.class})
  protected ResponseEntity<Object> handleIllegalArgument(
      IllegalArgumentException ex, WebRequest request) {
    String bodyOfResponse = "请求参数不合法：" + ex.getMessage();
    return handleExceptionInternal(
        ex, bodyOfResponse, new HttpHeaders(), HttpStatus.BAD_REQUEST, request);
  }

  /**
   * 处理方法参数验证不合法异常的方法 当方法参数验证失败时调用此方法
   *
   * @param ex 方法参数验证不合法异常
   * @param headers HTTP响应头
   * @param status HTTP状态码
   * @param request Web请求对象
   * @return 返回包含验证错误信息的HTTP响应实体
   */
  @Override
  protected ResponseEntity<Object> handleMethodArgumentNotValid(
      MethodArgumentNotValidException ex,
      @SuppressWarnings("NullableProblems") HttpHeaders headers,
      HttpStatusCode status,
      @SuppressWarnings("NullableProblems") WebRequest request) {
    Map<String, String> errors = new HashMap<>();
    ex.getBindingResult()
        .getAllErrors()
        .forEach(
            (error) -> {
              String fieldName = ((FieldError) error).getField();
              String errorMessage = error.getDefaultMessage();
              errors.put(fieldName, errorMessage);
            });

    Map<String, Object> body = new HashMap<>();
    body.put("timestamp", OffsetDateTime.now());
    body.put("status", status.value());
    body.put("errors", errors);

    return new ResponseEntity<>(body, headers, status);
  }

  /** 捕获 ResponseStatusException，避免堆栈直接返回给前端。 */
  @ExceptionHandler(ResponseStatusException.class)
  public ResponseEntity<Object> handleResponseStatusException(
      ResponseStatusException ex, WebRequest request) {
    log.warn("业务处理失败：{}", ex.getReason());
    return handleExceptionInternal(
        ex,
        ex.getReason(),
        new HttpHeaders(),
        HttpStatus.valueOf(ex.getStatusCode().value()),
        request);
  }

  /** 兜底处理所有未捕获的异常，返回友好的中文提示。 */
  @ExceptionHandler(Exception.class)
  public ResponseEntity<Object> handleGenericException(Exception ex, WebRequest request) {
    log.error("系统处理请求时发生未预期异常", ex);
    return handleExceptionInternal(
        ex,
        "系统处理请求时发生异常，请稍后重试",
        new HttpHeaders(),
        HttpStatus.INTERNAL_SERVER_ERROR,
        request);
  }
}
